// 导入路由
import router from './router'

// 导入 store 模块
import store from './store'

// 导入 动态路由数组(所有)
import { asyncRoutes } from '@/router'

// 导入进度条插件以及样式
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

// 拿到拼接浏览器标题的方法
import getPageTitle from '@/utils/get-page-title'

// 声明白名单
const whiteList = ['/login', '404']

// 路由的前置守卫
router.beforeEach(async (to, form, next) => {
  console.log(to.path)
  // 路由发生页面切换时,切换浏览器上的标题(动态的)
  // document.title = '标题内容'
  // 尽量不设置成固定的值(直接拼接),因为不方便维护和修改(封装成全局配置放到settings.js)
  document.title = getPageTitle(to.meta.title)

  // 当访问某一个路由的时候,需要直接显示进度条
  NProgress.start()

  // 获取 token
  const token = store.state.user.token

  // 判断: token 是否存在
  if (token) {
    // 判断用户访问的是否是登陆页面
    if (to.path === '/login') {
      // 如果有 token ，说明登录了，访问到又是登录页面，直接跳转到主页即可
      // 不需要用户进行重复登录操作
      next('/')
    } else {
      // 在放行之前，先行获取用户新的数据，在获取到数据以后，在进行跳转
      // 为什么需要在这里调用呢？
      // 为了后面做权限管理功能做铺垫

      // 改装: 判断拿不到用户的id, 就认为vuex里还没有保存用户的信息, 需要获取
      // 如果拿到用户的id, 证明vuex里有用户信息, 不必发送请求, 直接跳转
      if (!store.getters.userId) {
        const menusArr = await store.dispatch('user/getUserInfo')
        // console.log(menusArr)
        // 先测测动态路由8个对象能否用addRoute动态添加 (v)
        // 用规则数组里的标记一个个判断
        const resultArr = asyncRoutes.filter(routerObj => {
          return menusArr.includes(routerObj.children[0].name)
        })
        // 等待动态的路由筛选后, 把404加到后面去
        resultArr.push({ path: '*', redirect: '/404', hidden: true })
        // 过滤后的动态路由规则对象数组
        // 注意: 退出登录的时候, 走user/logout清除user模块用户token和userInfo信息, 重新登录的时候, if又会进来 (是自己清空的不是浏览器刷新回归初始化)
        // if进来以后, 又在8个对象路由数组再次筛选
        // 没刷新网页, router路由对象还在内存里, 又再次一次往里加入重复的路由对象->导致vue-router报警, 重复定义路由name
        // 解决: 退出登录的时候, 把路由对象内存里路由表回归初始化
        router.addRoutes(resultArr)
        // 还要往vuex里存一份(左侧导航生成负责)
        store.commit('permission/setRoutes', resultArr)

        // 会导致路由再次尝试跳转, 但是路由表里已经有动态了可以匹配
        next({
          path: to.path,
          replace: true // 替换当前页面(不产生回退记录)
        })
      }

      next()
    }
  } else {
    // 判断访问的地址是否在白名单中
    // includes 用来判断数组中是否存在某个字符串，如果存在，返回 true，否则返回 false
    if (whiteList.includes(to.path)) {
      next()
    } else {
      // 如果访问的页面不在白名单中
      next('/login')
    }
  }

  // 强制关闭进度条,解决一些特殊极端的情况下,进度条不关闭的情况(例如退出出错,进度条不关闭)
  NProgress.done()
})

// 路由的后置守卫
router.afterEach((to, form) => {
  // 进入路由以后,需要隐藏进度条
  NProgress.done()
})
